#include "cmdTask.h"

/*
 * 建立目录栈
 * 返回值为真：路径正确；假，路径错误
 * 用于获得当前的虚假工作路径、绝对工作路径
 *
 */

bool _get_dirStack(task_t *ptask, // 任务结构体
		   _dirStack_t *dirstack, // 目录栈地址
		   char *absDir[], // 绝对目录地址
		   char *fakeDir[] // 相对目录地址
)
{
	const char root[] =
		"/home/lunisolar/GroupWork/serverFrame/src/netdisk/"; //TODO 修改ming为用户名
	/* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
	char *cmdPath = strdup(ptask->_data);
	if (cmdPath == NULL) {
		fprintf(stderr, "empty path.\n");
		return false;
	}
	/* printf("cmdPath = %s\n", cmdPath); */
	char curpath[4096] = { 0 };
	char *token = strtok(cmdPath, "/");

	while (token) {
		/* printf("token = %s\n", token);// test */
		if (strcmp(token, ".") == 0) {
			token = strtok(NULL, "/");
			/* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
			continue;
		} else if (strcmp(token, "..") == 0) {
			if (_dirStack_pop(dirstack) == 1) {
				/* popFlag = true; */
				return false;
			}
		} else if (token) {
			_dirStack_push(dirstack, token);
		} else {
			break;
		}

		/* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
		token = strtok(NULL, "/");
	}

	strcpy(curpath, root);
	strcat(curpath, _dirStack_getDir(dirstack));
	curpath[strlen(curpath) - 1] = '\0';
	/* printf("curpath = %s\n", curpath); */

	char absstr[4096] = { 0 };
	strcat(absstr, root);
	strcat(absstr, curpath + strlen(root));
	/* printf("absolute path = %s\n", absstr); */
	/* printf("cd token = %s\n", token); */

	char fakerRoot[4096] = { 0 };
	strcat(fakerRoot, "~/netdisk/");
	strcat(fakerRoot, curpath + strlen(root));
	/* printf("fakeRoot = %s\n", fakerRoot); */

	//*absDir = (char*)calloc(strlen(absstr), sizeof(char));
	//*fakeDir = (char*)calloc(strlen(fakerRoot), sizeof(char));
	*absDir = strdup(absstr);
	*fakeDir = strdup(fakerRoot);

	/* printf("_get_dirStack end\n"); */

	return true;
}

/* 命令cd */
void cmdCd(task_t *ptask, user_context *puser)
{
	printf(">CD-------------------------------------------\n");

	char curDir[4096] = { 0 };
	getcwd(curDir, sizeof(curDir));
	strcat(curDir, "/netdisk/");
	strcat(curDir, _dirStack_getDir(&puser->dirStack));
	printf("curDir(before cd) = %s\n", curDir);
	strcat(curDir, ptask->_data);
	if (access(curDir, F_OK) != 0) {
		fprintf(stderr, "CD FAILED : directory.\n");
		//free(cmdPath);// TODO
		return;
	}

	char *absDir;
	char *fakeDir;

	// 临时目录栈 用于在pop错误时恢复原来的目录
	_dirStack_t tmpStack;
	_dirStack_init(&tmpStack);
	_dirStack_copy(&tmpStack, &puser->dirStack);

	printf("curstack = %s\n", _dirStack_getDir(&puser->dirStack));
	/* printf("tmpstack = %s\n", _dirStack_getDir(&tmpStack)); */

	if (_get_dirStack(ptask, &puser->dirStack, &absDir, &fakeDir) ==
	    false) {
		fprintf(stderr, "CD FAILED : no access right.\n");
		_dirStack_copy(&puser->dirStack, &tmpStack);
		printf("curstack = %s\n", _dirStack_getDir(&puser->dirStack));
		/* printf("tmpstack = %s\n", _dirStack_getDir(&tmpStack)); */
		return;
	}
	printf("curFakeDir(after cd) = %s\n", fakeDir);
	printf("curAbsDir(after cd) = %s\n", absDir);

	// 如果获取目录成功，则继续处理
	printf("CD SUCCESS!\n");
}

/* 命令ls */
void cmdLs(task_t *ptask, user_context *puser)
{
	printf(">LS-------------------------------------------\n");

	char *absDir;
	char *fakeDir;
	if (_get_dirStack(ptask, &puser->dirStack, &absDir, &fakeDir) ==
	    false) {
		fprintf(stderr, "LS FAILED: cant open dir.\n");
		return;
	}
	//printf("absDir = %s\n", absDir);
	//printf("fakeDir = %s\n", fakeDir);
	struct stat st;
	int ret = stat(absDir, &st);
	ERROR_CHECK(ret, -1, "lstat");
	if (!S_ISDIR(st.st_mode)) {
		fprintf(stderr, "LS FAIRED: not a directory.\n");
		return;
	}
	DIR *dir = opendir(absDir);
	ERROR_CHECK(dir, NULL, "open dir");

	struct dirent *entry;
	int rowLimit = 0;
	while ((entry = readdir(dir)) != NULL) {
		printf("%s ", entry->d_name);
		++rowLimit;
		if (rowLimit >= 8) { // 一行限制8个
			rowLimit = 0;
			printf("\n");
		}
	}
	printf("\n");

	printf(" LS SUCCESS!\n");
}

/* 命令pwd */
void cmdPwd(task_t *ptask, user_context *puser)
{
	printf(">PWD-------------------------------------------\n");
	char *absDir;
	char *fakeDir;
	if (_get_dirStack(ptask, &puser->dirStack, &absDir, &fakeDir) ==false) {
		printf("PWD FAILED!\n");
		return;
	}
	printf("pwd = %s\n", fakeDir);
	send(ptask->_clientFd, fakeDir, strlen(fakeDir), 0);
	printf("PWD SUCCESS!\n");
}